﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Logging;
using StyleMVVM.Utilities;
using StyleMVVM.View;
#if !DOT_NET
using Windows.System.Threading;
using Windows.UI.Core;
#else
using System.Threading;
#endif
#if NETFX_CORE
using Windows.UI.Xaml;

#else
using System.Windows;

#endif

namespace StyleMVVM.Messenger
{
	internal class WeakMessageHandlerWrapper : IMessageHandlerWrapper
	{
		private readonly WeakDelegate action;

		public WeakMessageHandlerWrapper(Delegate callback, bool background)
		{
			action = new WeakDelegate(callback);

			Background = background;
		}

		public WeakMessageHandlerWrapper(object target, MethodInfo methInfo, bool background)
		{
			action = new WeakDelegate(target, methInfo);

			Background = background;
		}

		public bool Background { get; private set; }

		public bool IsAlive
		{
			get { return action.IsAlive; }
		}

		public object Target
		{
			get { return action.Target; }
		}

		public MethodInfo Method
		{
			get { return action.MethodInfo as MethodInfo; }
		}

		public bool Execute(object value)
		{
			object target = action.Target;

			if (target != null)
			{
				if (!Background)
				{
					var dispatcher = ViewHelper.MainDispatcher;

#if NETFX_CORE

					if (dispatcher != null &&
					    !dispatcher.HasThreadAccess)
					{
						dispatcher.RunAsync(CoreDispatcherPriority.Normal,
						                    () =>
							                    {
								                    try
								                    {
									                    action.Invoke(value);
								                    }
								                    catch (Exception exp)
								                    {
									                    Logger.Error(
										                    "Exception thrown while executing message async on dispatcher handler",
										                    GetType().FullName,
										                    exp);
								                    }
							                    });
					}

#elif WINDOWS_PHONE

					if (dispatcher != null && !dispatcher.CheckAccess())
					{
						dispatcher.BeginInvoke(
							() =>
								{
									try
									{
										action.Invoke(value);
									}
									catch (Exception exp)
									{
										Logger.Error(
											"Exception thrown while executing message async on dispatcher handler", GetType().FullName, exp);
									}
								});
					}
#elif DOT_NET
					if (dispatcher != null && !dispatcher.CheckAccess())
					{
						dispatcher.BeginInvoke(new Action(
							                       () =>
								                       {
									                       try
									                       {
										                       action.Invoke(value);
									                       }
									                       catch (Exception exp)
									                       {
										                       Logger.Error(
											                       "Exception thrown while executing message async on dispatcher handler",
											                       GetType().FullName,
											                       exp);
									                       }
								                       }));
					}
#endif
					else
					{
						try
						{
							action.Invoke(value);
						}
						catch (Exception exp)
						{
							Logger.Error(
								"Exception thrown while executing message on dispatcher handler", GetType().FullName, exp);
						}
					}
				}
				else
				{
#if DOT_NET
					ThreadPool.QueueUserWorkItem(
#else
					ThreadPool.RunAsync(
#endif

						(x) =>
							{
								try
								{
									action.Invoke(value);
								}
								catch (Exception exp)
								{
									Logger.Error(
										"Exception thrown while executing message in background handler", GetType().FullName, exp);
								}
							});
				}

				return true;
			}

			return false;
		}
	}
}